package com.jiaai.web.pay;

import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.xml.parsers.ParserConfigurationException;

import org.apache.log4j.Logger;
import org.xml.sax.SAXException;


public class SignUtil {
	private static Logger logger = Logger.getLogger(SignUtil.class);
	private  static String PAY_KEY="1qaz@WSX@#$%^$";
	 public static String getToken(Map<String, String> map) {
		     List<String> list = new ArrayList<String>();
			for (Map.Entry<String, String> entry : map.entrySet()) {
				if(!"".equals(entry.getValue())) {
					list.add(entry.getKey() + "=" + entry.getValue() + "&");
				}
			}
			int size = list.size();
			String[] arrayToSort = list.toArray(new String[size]);
			Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER);
			StringBuilder sb = new StringBuilder();
			for (int i = 0; i < size; i++) {
				sb.append(arrayToSort[i]);
			}
	        MessageDigest md = null;
	        String tmpStr = null;
	        String str = sb.toString();
	        try {
	            md = MessageDigest.getInstance("SHA-1");
	            // 将三个参数字符串拼接成一个字符串进行sha1加密
	            byte[] digest = md.digest(str.substring(0, str.length()-1).getBytes());
	            //将字节数组转成字符串
	            tmpStr = byteToStr(digest);
	        } catch (NoSuchAlgorithmException e) {
	           logger.error("签名失败");
	        }
	        return tmpStr.toLowerCase();
	    }
	 
	 
	//将加密后的字节数组变成字符串
	    private static String byteToStr(byte[] byteArray) {
	        String strDigest = "";
	        for (int i = 0; i < byteArray.length; i++) {
	            strDigest += byteToHexStr(byteArray[i]);
	        }
	        return strDigest;
	    }
	 
	    private static String byteToHexStr(byte mByte) {
	        char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A',
	                'B', 'C', 'D', 'E', 'F' };
	        char[] tempArr = new char[2];
	        tempArr[0] = Digit[(mByte >>> 4) & 0X0F];
	        tempArr[1] = Digit[mByte & 0X0F];
	 
	        String s = new String(tempArr);
	        return s;
	    }
	    
		/**
		 * 生成随机数
		 * 
		 * @return
		 */
		public static String createNonceStr() {
			return UUID.randomUUID().toString().replaceAll("-", "");
		}

		/**
		 * 生成时间戳
		 */
		public static String createTimestamp() {
			return Long.toString(System.currentTimeMillis() / 1000);
		}

		/**
		 * 检验API返回的数据里面的签名是否合法，避免数据在传输的过程中被第三方篡改
		 * 
		 * @param map
		 *            API返回的XML数据字符串
		 * @return API签名是否合法
		 * @throws Exception
		 * @throws ParserConfigurationException
		 * @throws IOException
		 * @throws SAXException
		 */
		public static boolean checkSign(Map<String, String> map)
				throws Exception {
			String signFromAPIResponse = map.get("sign").toString();
			if (signFromAPIResponse == "" || signFromAPIResponse == null) {
				logger.warn("API返回的数据签名数据不存在，有可能被第三方篡改!!!");
				return false;
			}
			logger.info("服务器回包里面的签名是:" + signFromAPIResponse);
			// 清掉返回数据对象里面的Sign数据（不能把这个数据也加进去进行签名），然后用签名算法进行签名
			map.put("sign", "");
			// 将API返回的数据根据用签名算法进行计算新的签名，用来跟API返回的签名进行比较
			String signForAPIResponse = getSign(map);

			if (!signForAPIResponse.equals(signFromAPIResponse)) {
				// 签名验不过，表示这个API返回的数据有可能已经被篡改了
				logger.warn("API返回的数据签名验证不通过，有可能被第三方篡改!!!");
				return false;
			}
			logger.info("恭喜，API返回的数据签名验证通过!!!");
			return true;
		}

		/**
		 * 签名算法
		 * 
		 * @param map
		 *            要参与签名的数据Map
		 * @return 签名
		 */
		public static String getSign(Map<String, String> map) {
			List<String> list = new ArrayList<String>();
			for (Map.Entry<String, String> entry : map.entrySet()) {
				if(!"".equals(entry.getValue())) {
					list.add(entry.getKey() + "=" + entry.getValue() + "&");
				}
			}
			int size = list.size();
			String[] arrayToSort = list.toArray(new String[size]);
			Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER);
			StringBuilder sb = new StringBuilder();
			for (int i = 0; i < size; i++) {
				sb.append(arrayToSort[i]);
			}
			return MD5.MD5Encode(
					sb.toString() + "key=" + PAY_KEY).toUpperCase();
		}

		
		 public static String getSignature(Map<String, String> map) {
			     List<String> list = new ArrayList<String>();
				for (Map.Entry<String, String> entry : map.entrySet()) {
					if(!"".equals(entry.getValue())) {
						list.add(entry.getKey() + "=" + entry.getValue() + "&");
					}
				}
				int size = list.size();
				String[] arrayToSort = list.toArray(new String[size]);
				Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER);
				StringBuilder sb = new StringBuilder();
				for (int i = 0; i < size; i++) {
					sb.append(arrayToSort[i]);
				}
		        MessageDigest md = null;
		        String tmpStr = null;
		        String str = sb.toString();
		        try {
		            md = MessageDigest.getInstance("SHA-1");
		            // 将三个参数字符串拼接成一个字符串进行sha1加密
		            byte[] digest = md.digest(str.substring(0, str.length()-1).getBytes());
		            //将字节数组转成字符串
		            tmpStr = byteToStr(digest);
		        } catch (NoSuchAlgorithmException e) {
		           logger.error("签名失败");
		        }
		        return tmpStr.toLowerCase();
		    }
		 
}
